#include <iostream>
#include <vector>
#include <iterator>

#include "cuda_runtime.h"

#define N 100000000

using namespace std;


__global__ void add(float* x, const int v, const int size)
{
    int t_index = threadIdx.x + blockIdx.x * blockDim.x;
    if(t_index < size){
        x[t_index] -= t_index;
    }
}

bool hello_world()
{ 
    // Step 1: host(cpu) 端数据准备
    vector<float> h_vec;
    h_vec.resize(N);
    for (size_t i = 0; i < N; i++){
        h_vec[i] = i;
    }

    // Step 2: device(GPU) 端申请内存
    float *d_x;
    int t_bytes = N * sizeof(float);
    cudaMalloc((void**)&d_x, t_bytes);

    // Step 3: copy 数据从 host 到 device
    cudaMemcpy((void*) d_x, (void*)h_vec.data(), t_bytes, cudaMemcpyHostToDevice);

    // Step 4: 配置需要的线程
    dim3 Db(32);
    dim3 Dg((N + Db.x - 1) / Db.x);

    // Step 5: 执行核函数
    add<<<Dg, Db>>>(d_x, 100, N);
    
    // Step 6: copy 数据从 device 到 host
    cudaMemcpy((void*)h_vec.data(), (void*)d_x, t_bytes, cudaMemcpyDeviceToHost);

    // Step 7: 释放内存
    cudaFree(d_x);

    // Step 8: check result
    float t_sum(0);
    for (size_t i = 0; i < N; i++){
        t_sum += h_vec[i];
    }
    if(t_sum > 1 || t_sum < -1){
        cout<<"Failed: the result must be 0, but "<<t_sum<<" is the result now"<< endl;
        return false;
    }else{
        cout<<"Successed: the result is "<<t_sum<<endl;
        return true;
    }

}
